package moTSP;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Random;

/**
 * Przechowuje informacje o ilości miast oraz odległościach między miastami (kosztami podróży).
 */
public class TownsMap {
    
    private int numOfTowns;
    private int numOfObjectives;
    
    double[][][] costsOfTravels;
    
    public TownsMap(String path) {
        
        try {
            BufferedReader in = new BufferedReader(new FileReader(path));     

            // first line is number of towns
            String[] firstLineSplited = in.readLine().split(" ");
            this.numOfTowns = Integer.parseInt(firstLineSplited[0]);
            this.numOfObjectives = Integer.parseInt(firstLineSplited[1]);

            costsOfTravels = new double[this.numOfTowns][this.numOfTowns][this.numOfObjectives];

            String str;

            int from = 0;
            while ((str = in.readLine()) != null)
            {
                String[] splitedLineStr = str.split(";");

                int to = 0;
                for (String objectivesToTownStr : splitedLineStr) {
                    String[] objectivesSplitedStr = objectivesToTownStr.split(",");
                    for (int objNum = 0; objNum < this.numOfObjectives; objNum++) {
                        costsOfTravels[from][to][objNum] = Double.parseDouble(objectivesSplitedStr[objNum]);
                    }
                    to++;
                }
                from++;
            }
            in.close();
        }
        catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public int getNumOfTowns() {
        return numOfTowns;
    }

    public int getNumOfObjectives() {
        return numOfObjectives;
    }
    
    public double getTravelCost(int from, int to, int objNum) {
        return costsOfTravels[from][to][objNum];
    }
    
    /**
     * GENEROWANIE ODLEGŁOŚCI MIĘDZY MIASTAMI.
     * 
     * "To generate a bi-objective test 
     * instance with n cities, a random distribution of cities in a [0; n] £ [0; n] area is
     * generated for each objective. The travel cost between any two cities is set to be
     * the distance between them."
     */
    public static void main(String[] args) {
        
        if (args.length != 3) {
            System.out.println("Argumenty [ilosc_miast] [ilosc_objectives] [plik_docelowy]");
            System.exit(1);
        }
        
        int numOfTowns = Integer.parseInt(args[0]);
        int numOfObjectives = Integer.parseInt(args[1]);
        String targetFilepath = args[2];
        
        System.out.println("numOfTowns = "+numOfTowns);
        System.out.println("numOfObjectives = "+numOfObjectives);
        System.out.println("targetFilepath = "+targetFilepath);
        
        double[][][] costsOfTravels = new double[numOfTowns][numOfTowns][numOfObjectives];
        
        Random rand = new Random();
        
        for (int objectiveNum = 0; objectiveNum < numOfObjectives; objectiveNum++) {
            
            double[][] townsLocations = new double[numOfTowns][numOfObjectives];
            for (int i = 0; i < numOfTowns; i++) {
                townsLocations[i][0] = rand.nextDouble();
                townsLocations[i][1] = rand.nextDouble();
            }
            
            for (int from = 0; from < numOfTowns; from++) {
                for (int to = 0; to < numOfTowns; to++) {
                    
                    double distance = 0.0;
                    if (from != to) {
                        distance = calculateDist(
                                townsLocations[from][0],townsLocations[from][1],
                                townsLocations[to][0],  townsLocations[to][1]);
                    }
                    costsOfTravels[from][to][objectiveNum] = distance;
                }
            }
        }
        
        try {
            BufferedWriter out = new BufferedWriter(new FileWriter(targetFilepath));
            
            // pierwsza linia
            out.write(""+numOfTowns+" "+numOfObjectives+"\n");

            // zapisywanie do pliku
            for (int from = 0; from < numOfTowns; from++) {
                for (int to = 0; to < numOfTowns; to++) {
                    for (int j = 0; j < numOfObjectives; j++) {
                        out.write(""+costsOfTravels[from][to][j]);
                        if (j != numOfObjectives - 1) {
                            out.write(",");
                        }
                    }
                    if (to != numOfTowns - 1) {
                        out.write(";");
                    }
                }
                out.write("\n");
            }
            out.close();
        }
        catch (IOException e) {
            e.printStackTrace();
        }
        System.out.println("Generaowanie pliku z miastami powiodlo się");
    }

    private static double calculateDist(double x1, double y1, double x2, double y2) {
        return Math.sqrt(Math.pow(x1-x2, 2)+Math.pow(y1-y2, 2));
    }
}
